搜索 K
Appearance
博客正在加载中...
Appearance
最原始的日志输出方式
在我们编写程序的时候,为了方便观察变量的值,我们可以用 System.out.println() 打印变量。
有时候简单的加个打印语句,断点调试有点麻烦:需要设置断点,然后一步步执行观察;如果有问题,再重新打断点,重新调试……
当然,断点调试也有优点,对于复杂的的情况,能够很好的跟踪各个变量的值和变化情况,有助于理解和跟踪程序(如果全部用 print 打印出来,需要一大堆代码,并且打印出来一大堆信息,容易眼花缭乱)
这种直接打印到控制台的办法,也叫 print 大法。目前业内不少人认为 printf 方法很简单很 low;但是只要能快速解决问题,用用也无妨,特别是自己练习一些简单的代码的时候。
接下来讲讲 print 大法的不足:
不知道输出的语句是在哪个类,哪个线程里出来的
不知道什么时候前后两句输出间隔了多少时间
日志内容混杂,比如正常执行的日志和错误的日志混杂在一起,难以跟踪。
如果想将日志保存到文件?保存到数据库?print 不支持,只能自己写个 IO 程序去存储
需要频繁修改源代码。例如,代码已经编写完成,那么无用的 prinf 语句怎么办?肯定是删除,不然整个 Java 代码导出充斥着打印语句,可读性很差;
但如果后面发现又有问题,怎么办?把 prinf 语句加上去……
改来改去后,非常麻烦。要不改完代码后给 print 语句加个注释? 但这样可读性还是很差……
需要自己设置打印的格式,例如执行到哪一步了,就输出“目前执行到第 x 步,变量的值为:”, 或者输出“有异常!请即使处理”
..............................................
断言(Assertion)是一种调试程序的方式。在 Java 中,使用 assert 关键字来实现断言。
我们先看一个例子:
public static void main(String[] args) {
double x = Math.abs(-123.45);
assert x >= 0;
System.out.println(x);
}语句 assert x >= 0; 即为断言,断言条件 x >= 0 预期为 true。如果计算结果为 false,则断言失败,抛出 AssertionError。
使用 assert 语句时,还可以添加一个可选的断言消息:
assert x >= 0 : "x must >= 0";这样,断言失败的时候,AssertionError 会带上消息 x must >= 0,更加便于调试。
Java 断言的特点是:断言失败时会抛出 AssertionError,导致程序结束退出。因此,断言不能用于可恢复的程序错误,只应该用于开发和测试阶段。
对于可恢复的程序错误,不应该使用断言。例如:
void sort(int[] arr) {
assert arr != null;
}应该抛出异常并在上层捕获:
void sort(int[] arr) {
if (arr == null) {
throw new IllegalArgumentException("array cannot be null");
}
}当我们在程序中使用 assert 时,例如,一个简单的断言:
// assert
public class Main {
public static void main(String[] args) {
int x = -1;
assert x > 0;
System.out.println(x);
}
}断言 x 必须大于 0,实际上 x 为 -1,断言肯定失败。执行上述代码,发现程序并未抛出 AssertionError,而是正常打印了 x 的值。
这是怎么肥四?为什么 assert 语句不起作用?
这是因为 JVM 默认关闭断言指令,即遇到 assert 语句就自动忽略了,不执行。
要执行 assert 语句,必须给 Java 虚拟机传递 -enableassertions(可简写为 -ea)参数启用断言。所以,上述程序必须在命令行下运行才有效果:
$ java -ea Main.java
Exception in thread "main" java.lang.AssertionError
at Main.main(Main.java:5)还可以有选择地对特定地类启用断言,命令行参数是:-ea:com.itranswarp.sample.Main,表示只对 com.itranswarp.sample.Main 这个类启用断言。
或者对特定地包启用断言,命令行参数是:-ea:com.itranswarp.sample...(注意结尾有 3 个 .),表示对 com.itranswarp.sample 这个包启动断言。
实际开发中,很少使用断言。更好的方法是编写单元测试,后续我们会讲解 JUnit 的使用。
print 大法简单,人人都会用;但也有不少缺点,这些缺点决定了 print 大法不适合用在大型的项目中。
断言是一种调试方式,断言失败会抛出 AssertionError,只能在开发和测试阶段启用断言;对可恢复的错误不能使用断言,而应该抛出异常;断言很少被使用,更好的方法是编写单元测试。
接下来我们将介绍日志框架。